
package body Block is

   procedure Read_Block_Header(Stream : not null access Ada.Streams.Root_Stream_Type'Class; Item : out Block_Header) is
      Byte : Unsigned_8;
      Timecode : Unsigned_16;
   begin
      Element_Size_Type'Read(Stream, Item.Track);

      Unsigned_8'Read(Stream, Byte);
      Timecode := Unsigned_16(Byte);
      Timecode := Shift_Left(Value  => Timecode, Amount => 8);
      Unsigned_8'Read(Stream, Byte);
      Timecode := Timecode + Unsigned_16(Byte);
      if(Timecode and 16#8000#) > 0 then
         -- negative (Two's complement)
         Item.Timecode := Integer_16(not Timecode);
         Item.Timecode := (Item.Timecode + 1) * (-1);
      else
         -- positive
         Item.Timecode := Integer_16(Timecode);
      end if;

      Unsigned_8'Read(Stream, Byte);
      Item.Key_Frame := (Byte and 2#1000_0000#) > 0;
      Item.Invisible := (Byte and 2#0000_1000#) > 0;

      case Byte and 2#0000_0110# is
         when 2#0000_0000# =>
            Item.Lacing := NONE;
         when 2#0000_0010# =>
            Item.Lacing := XIPH;
         when 2#0000_0110# =>
            Item.Lacing := EBML;
         when 2#0000_0100# =>
            Item.Lacing := FIXED;
         when others =>
            Item.Lacing := NONE;
      end case;

      Item.Discardable := (Byte and 2#0000_0001#) > 0;

   end Read_Block_Header;

   procedure Read_Block_Frames(File : IO.File_Type; Block : out Block_Type) is
      Byte : Unsigned_8;
      Start_Index : constant Positive_Count := Index(File.File);
      Total_Size : constant Count := Count(Block.Size) - (Start_Index - Block.File_Index);
   begin
      case Block.Header.Lacing is
         when NONE =>
            Block.Frames_Count := 1;
            Block.Frames(1).File_Index := Index(File.File);
            Block.Frames(1).Size := Total_Size;
         when XIPH =>
            Unsigned_8'Read(File.File_Access, Byte);
            Block.Frames_Count := 1;
            Block.Frames(1).File_Index := Index(File.File);
         when EBML =>
            Block.Frames_Count := 1;
            Block.Frames(1).File_Index := Index(File.File);
         when FIXED =>
            Unsigned_8'Read(File.File_Access, Byte);
            Byte := Byte + 1; -- add one because lacing count is one less than total (why?)
            Block.Frames_Count := Byte;
            for I in 1..Byte loop
               Block.Frames(I).File_Index := Start_Index + (Count(I-1) * (Total_Size / Count(Byte)));
            end loop;
            -- make sure that last index does not overflow (should not happen)
            Block.Frames(Byte).File_Index := Block.File_Index + Count(Block.Size);
      end case;
   end Read_Block_Frames;
end Block;